import DataSource, { DataSourceMgr, DataSourceLoadingMap, DataSourceChartMap } from "../dataSource/dataSource"
import { EffectConfigMap } from "../core/effect";
import { EAxisChartDimension } from "../core/ChartType";
import { IAxisChartConfig } from "./AxisChart";
import { ICircleChartConfig } from "./CircleChart";
import { IRadarChartConfig } from "./RadarChart";
export const ChartIdMap = new Map<string, { parent: string, self: Chart<any> }>();



export interface IEvent {
    //redirect后，所属的结构组中被redirect的元素，active为true，其余都是false
    type: "redirect" | "setFilter",
    target: string,
    params?: any
}
enum EAxisType {
    Category = 'category',
    Value = "value",
    Time = 'time',
    Log = 'log'
}
export interface IChartConfig {
    id: string,
    title?: string;
    container: string,
    chartType: number,
    dataSourceURL: string,
    mateDataURL: string,
    parent: string;
    limit: number;
    events?: { [key: string]: IEvent };
    defaultFilter?: { [key: string]: any };
    defaultMateFilter?: { [key: string]: any };
    chartOptions: any;
}
export interface IReportConfig {
    chartStructureGroup: Array<Array<{ id: string, active: boolean }>>;
    charts: { [key: string]: IAxisChartConfig | IChartConfig | ICircleChartConfig | IRadarChartConfig };
}
export let CurrentActiveChart: Chart<any> | null = null;
const ChartConfigMap = new WeakMap<Chart<any>, Map<string, any>>();

export class ChartConfigMgr<T extends IChartConfig>{
    private config = new Map<keyof T, any>();
    private dataSourceMgr: DataSourceMgr;
    // computedConifgStrategy: (data: any) => void;
    constructor(config: { [key: string]: any }, dataSource: DataSourceMgr) {
        for (let key in config) {
            this.config.set(<keyof T>key, config[key]);
        }
        this.dataSourceMgr = dataSource;
        // this.computedConifgStrategy = computedFn;
    }
    getDataSource() {
        return this.dataSourceMgr;
    }
    setConfigValue(configKey: (keyof T), configVal: any) {
        this.config.set(configKey, configVal);
    }
    setConfig(configKey: (keyof T), configVal: any) {
        this.config.set(configKey, configVal);
        DataSourceLoadingMap.get(this.dataSourceMgr.getDataSource()) !== true && (EffectConfigMap.get(this) || []).forEach((fn) => {
            fn();
        })
    }
    getConfig(configKey?: (keyof T)) {
        if (configKey) {
            return this.config.get(configKey);
        } else {
            return this.config;
        }
    }
}

export default abstract class Chart<T extends IChartConfig> {
    id: string = "";
    protected ChartConfigMgr: ChartConfigMgr<T>;
    protected DataSourceMgr: DataSourceMgr;

    //以下属性用于构建逻辑树
    nextCharts: Array<Chart<T>> = [];
    prevCharts: Chart<T> | null = null;

    constructor(config: { [key: string]: any }, dataSource: DataSourceMgr, id?: string) {
        this.ChartConfigMgr = new ChartConfigMgr(config, dataSource);
        this.DataSourceMgr = dataSource;
        let currentCharts = DataSourceChartMap.get(this.DataSourceMgr);
        if (currentCharts) {
            currentCharts.push(this);
        } else {
            DataSourceChartMap.set(this.DataSourceMgr, [this]);
        }

        CurrentActiveChart = this;
        if (id && id != "")
            this.id = id;
        else {
            this.id = this.ChartConfigMgr.getConfig("id");
        }
    }
    abstract computedConifgStrategy(orignData: any): void;

    setConfig(configKey: (keyof T), configVal: any) {
        this.ChartConfigMgr.setConfig(configKey, configVal);
    }
    getConfig(configKey?: (keyof T)) {
        return this.ChartConfigMgr.getConfig(configKey);
    }
    setDataSourceFilter(params: any) {
        this.DataSourceMgr.setFilter(params);
    }
    renderCallBack!: () => void;
    focusReRender() {
        this.renderCallBack();
    }
    render() {
        this.renderCallBack();
    }
    create(fn: (chartConfigMgr?: ChartConfigMgr<T>, dataSource?: DataSourceMgr, reRender?: () => void, destroyMySelf?: () => void) => void) {
        CurrentActiveChart = this;
        this.renderCallBack = fn.bind(null,
            this.ChartConfigMgr,
            this.DataSourceMgr,
            this.focusReRender,
            this.destroyMySelf.bind(this));
    }
    /**
     * 销毁自身，当rerender再次被触发的时候，重新绘制
     */
    destroyMySelf() {
        const container = document.getElementById(this.ChartConfigMgr.getConfig("container"));
        if (container) {
            container.innerHTML = "";
        }
    }
}